package com.example.mobilesafe.dao;

import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Debug;

import com.example.mobilesafe.R;
import com.example.mobilesafe.domain.ProcessInfo;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ProcessInfoDao {

    /**
     * 获取进程总数的方法
     * @param context 上下文环境
     * @return
     */
    public static int getProcessCount(Context context){
        // 1.获取ActivityManager对象
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        // 2.获取正在运行的进程的集合
        List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
        // 3.返回集合的总数
        return runningAppProcesses.size();
    }

    /**
     * 获取可用空间的大小
     * @param context 上下文环境
     * @return 返回可用的内存数，bytes
     */
    public static long getAvailSpace(Context context){
        // 1.获取ActivityManager对象
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        // 2.构建存储可用内存的对象
        ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
        // 3.给MemoryInfo对象赋值（可用内存）
        activityManager.getMemoryInfo(memoryInfo);
        // 4.获取MemoryInfo中相应的可用内存大小
        return memoryInfo.availMem;
    }

    /**
     * 获取所有空间的大小
     * @param context 上下文环境
     * @return 返回可用的内存数，单位为bytes
     */
    @TargetApi(16)
    public static long getTotalSpace(Context context){
        if (Build.VERSION.SDK_INT >= 16){
            // api版本大于16的方式
            // 1.获取ActivityManager对象
            ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            // 2.构建存储可用内存的对象
            ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
            // 3.给MemoryInfo对象赋值（所有内存）
            activityManager.getMemoryInfo(memoryInfo);
            // 4.获取MemoryInfo中相应的所有内存大小
            return memoryInfo.totalMem;
        }else {
            // api版本小于16的方式
            // 如果你的api版本在16以下，需要读取proc/meminfo文件，读取第一行，获取数字字符，转换成bytes信息返回
            FileReader fileReader = null;
            BufferedReader bufferedReader = null;
            try {
                fileReader = new FileReader("proc/meminfo");
                bufferedReader = new BufferedReader(fileReader);
                String lineOne = bufferedReader.readLine();
                // 将字符串转换成字符数组
                char[] chars = lineOne.toCharArray();
                // 循环遍历每一个字符，如果此字符的ASCII码在0到9的区域内，说明此字符有效
                StringBuffer stringBuffer = new StringBuffer();
                for (char c : chars) {
                    if (c >= '0' && c <= '9'){
                        stringBuffer.append(c);
                    }
                }
                // 将字符数组转化成字符串，解析成long类型，并且乘1024转换成byte
                return Long.parseLong(stringBuffer.toString()) * 1024;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {

                    try {
                        if (fileReader != null && bufferedReader != null) {
                            fileReader.close();
                            bufferedReader.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            }
        }
        return 0;
    }

    /**
     * 获取进程信息的列表
     * @param context 上下文环境
     * @return 进程信息的列表
     */
    public static List<ProcessInfo> getProcessInfoList(Context context){
        // 获取进程相关信息

        // 0.创建ProcessInfo集合
        List<ProcessInfo> processInfoList = new ArrayList<>();
        // 1.获取ActivityManager对象和PackageManger管理者对象
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        PackageManager packageManager = context.getPackageManager();
        // 2.获取正在运行的进程的集合
        List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
        // 3.循环遍历上述集合，获取进程相关信息（名称，包名，图标，使用内存大小，是否为系统进程）
        for (ActivityManager.RunningAppProcessInfo runningAppProcess : runningAppProcesses) {
            ProcessInfo processInfo = new ProcessInfo();
            // 4.获取进程名称，即包名
            processInfo.setPackageName(runningAppProcess.processName);
            // 5.获取进程占用的内存大小（传递一个进程对应的pid数组）
            Debug.MemoryInfo[] processMemoryInfo = activityManager.getProcessMemoryInfo(new int[]{runningAppProcess.pid}); // 数组中索引为0的对象为当前线程的内存信息的对象
            Debug.MemoryInfo memoryInfo = processMemoryInfo[0];
            processInfo.setMemSize(memoryInfo.getTotalPrivateDirty() * 1024);
            try {
                ApplicationInfo applicationInfo = packageManager.getApplicationInfo(runningAppProcess.processName, 0);
                // 6.获取应用的名称
                processInfo.setName(applicationInfo.loadLabel(packageManager).toString());
                // 7.获取应用的图标
                processInfo.setIcon(applicationInfo.loadIcon(packageManager));
                // 8.判断是否为启动线程
                if ((applicationInfo.flags & applicationInfo.FLAG_SYSTEM) == applicationInfo.FLAG_SYSTEM){
                    processInfo.setSystem(true);
                }else {
                    processInfo.setSystem(false);
                }
            } catch (PackageManager.NameNotFoundException e) {
                // 需要处理，即非应用的无名称、无图标的进程
                processInfo.setName(runningAppProcess.processName);
                processInfo.setIcon(context.getResources().getDrawable(R.drawable.ic_launcher));
                processInfo.setSystem(true);
                e.printStackTrace();
            }
            processInfoList.add(processInfo);
        }
        return processInfoList;
    }

    /**
     * 杀死进程的方法
     * @param context 上下文环境
     * @param processInfo 传递进来的进程信息
     */
    public static void killProcess(Context context,ProcessInfo processInfo) {
        // 1.获取ActivityManager对象
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        // 2.杀死指定包名进程（需要声明权限）
        activityManager.killBackgroundProcesses(processInfo.getPackageName());
    }

    /**
     * 杀死全部进程的方法
     * @param context 上下文环境
     */
    public static void killAllProcess(Context context) {
        // 1.获取ActivityManager对象
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        // 2.获取正在运行的进程的集合
        List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
        // 3.循环遍历所有的进程，并且杀死
        for (ActivityManager.RunningAppProcessInfo runningAppProcess : runningAppProcesses) {
            // 4.除了手机卫士以外的应用，其他的进程都需要杀死
            if (runningAppProcess.processName.equals(context.getPackageName())){
                // 5.如果匹配上了手机卫士，则跳出本次循环，进行下一次循环
                continue;
            }
            activityManager.killBackgroundProcesses(runningAppProcess.processName);
        }
    }
}